Skip to main content

Everything

1. Pipes

Formatieren Daten im Template.

Beispiel:

<p>{{ price | currency:'EUR' }}</p>
<p>{{ today | date:'dd.MM.yyyy' }}</p>
<p>{{product.price | geld}}</p>

Eigene Pipe:

@Pipe({ name: 'geld' })
export class GeldPipe implements PipeTransform {
transform(value: number, currency: string = 'EUR'): string {
return new Intl.NumberFormat('de-DE', {
style: 'currency',
currency
}).format(value);
}
}

Anwendung: Datenformatierung, Übersetzungen, Berechnungen.

ng g p pipes/my-pipe


2. RxJS & Observables

Asynchrones Arbeiten mit Datenströmen.

Beispiel:

this.http.get<User[]>('/api/users')
.pipe(map(users => users.filter(u => u.active)))
.subscribe(activeUsers => this.users = activeUsers);

Anwendung: HTTP-Requests, Echtzeit-Updates (WebSocket), Event-Streams.


3. Forms

Zwei Varianten: Template-driven & Reactive Forms.

Reactive Example:

<form [formGroup]="form" (ngSubmit)="submit()">
<input formControlName="email"><br>
<input formControlName="password"><br>
<input formControlName="nickname"><br>
<button type="submit">Senden</button>
</form>
export class LoginComponent {
form = new FormGroup({
email: new FormControl('Email', Validators.required),
password: new FormControl('', Validators.required),
nickname: new FormControl('Nickname')
})

submit() {
if (this.form.valid) {
console.log('Form submitted:', this.form.value);
// Here you would typically send the form data to your backend
} else {
console.log('Form is invalid');
}
}
}

Complexeres beispiel:

form = new FormGroup({
emails: new FormArray([
new FormControl('', [Validators.required, Validators.email])
])
});

addEmail() {
(this.form.get('emails') as FormArray).push(
new FormControl('', [Validators.required, Validators.email])
);
}
<form [formGroup]="form" (ngSubmit)="submit()">
<div formArrayName="emails">
<div *ngFor="let email of form.get('emails').controls; let i = index">
<input [formControlName]="i">
</div>
</div>
<button (click)="addEmail()">Weitere E-Mail</button>
<button type="submit">Senden</button>
</form>

Weiteres komplexes beispiel

form = new FormGroup({
password: new FormControl('', Validators.required),
confirm: new FormControl('', Validators.required),
}, { validators: this.passwordsMatch });

passwordsMatch(group: AbstractControl): ValidationErrors | null {
const pw = group.get('password')?.value;
const confirm = group.get('confirm')?.value;
return pw === confirm ? null : { notMatching: true };
}
<form [formGroup]="form" (ngSubmit)="submit()">
<input formControlName="password" type="password">
<input formControlName="confirm" type="password">
<div *ngIf="form.errors?.notMatching">Passwörter stimmen nicht überein</div>
<button type="submit">Senden</button>
</form>


4. Interceptors

HTTP-Anfragen zentral abfangen & modifizieren.

ng g interceptor auth

Beispiel:

main.ts:

bootstrapApplication(AppComponent, {
providers: [
provideRouter(routes),
provideHttpClient(
withInterceptors([loggingInterceptor]),
)
]
});
export const loggingInterceptor: HttpInterceptorFn = (req, next) => {
console.log('Request made with ', req);
return next(req).pipe(
tap((event: { type: any; }) => {
if (event.type === HttpEventType.Response) {
console.log('Response received with ', event);
}
})
);
};

und bei einem token:

export const authInterceptor: HttpInterceptorFn = (req, next) => {
const token = localStorage.getItem('token'); // oder aus Service
const authReq = token
? req.clone({ setHeaders: { Authorization: `Bearer ${token}` } })
: req;
return next(authReq);
};

Anwendung: Authentifizierung, Logging, Error Handling.


5. Signals (neu in Angular 16)

Reaktive Zustände ohne RxJS.

Beispiel:

const count = signal(0);

// Reaktive Wirkung
effect(() => {
console.log('Count hat sich geändert:', count());
});

count.set(1); // -> löst effect aus
count.update(c => c + 1); // -> löst effect erneut aus

Anwendung: State Management, UI-Updates ohne Observable-Boilerplate.


6. Dynamic Component Loading

Komponenten zur Laufzeit laden.

Beispiel:

@ViewChild('container', { read: ViewContainerRef }) vcr!: ViewContainerRef;

loadComponent() {
const compRef = this.vcr.createComponent(MyDynamicComponent);
compRef.instance.data = 'Hallo';
}

Anwendung: Modale, dynamische Dashboards, Plug-in-Systeme.


7. Testing

Unit-Tests & End-to-End-Tests.

Unit-Test:

it('should add two numbers', () => {
expect(service.add(2,3)).toBe(5);
});

Anwendung: Qualitätssicherung, Fehlervermeidung.

.spec. files sind beriets unit tests.

bei http problemen:

import { NgModule } from '@angular/core';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ActivatedRoute } from '@angular/router';

@NgModule({
imports: [HttpClientTestingModule],
providers: [
{ provide: ActivatedRoute, useValue: { snapshot: { params: {} } } }
],
exports: [HttpClientTestingModule]
})
export class TestUtilsModule {}

und dass in jedem test importieren

ansonsten e2e tests:

npm install cypress --save-dev

npx cypress open

cypress run

describe('template spec', () => {
it('passes', () => {
cy.visit('https://localhost:4200')
cy.contains('Produkt Liste')

})
})

8. Internationalisierung (i18n)

Mehrsprachige Apps.

Beispiel:

npm install @ngx-translate/core @ngx-translate/http-loader --save

ng add @angular/localize

bootstrapApplication(AppComponent, {
providers: [
provideRouter(routes),
provideHttpClient(
withInterceptors([loggingInterceptor]),
),
importProvidersFrom(
TranslateModule.forRoot({
loader: { provide: TranslateLoader, useClass: TranslateHttpLoader }
})
),
{
provide: TRANSLATE_HTTP_LOADER_CONFIG,
useValue: { prefix: './assets/i18n/', suffix: '.json' }
}
]
});
export class HomeComponent {
constructor(private translate: TranslateService) {}
switchLanguage(lang: string) {
this.translate.use(lang);
}
}

<h1>{{ 'TITLE' | translate }}</h1>

<app-product-list></app-product-list>
<button (click)="switchLanguage('de')">Deutsch</button>
<button (click)="switchLanguage('en')">Englisch</button>
{
"TITLE": "Mein Angular Shop",
"BUY": "Kaufen"
}
// src/assets/i18n/de.json
// alle anderen module:
imports: [
TranslateModule
],

<h1>{{'BUY' | translate}}</h1>

Dann mit Angular CLI extrahieren & übersetzen.

Anwendung: Globale Apps, Mehrsprachigkeit.




11. PWA-Unterstützung

Offlinefähige Web-App.

Beispiel:

ng add @angular/pwa
ng build --configuration production
npm install -g http-server

npx http-server -p 8080 ./dist/shop-frontend/browser

ngsw-config.json bearbeiten für caching

Anwendung: Offline-Nutzung, Push-Benachrichtigungen.


12. Preloading Strategies

Module im Hintergrund vorladen.

Beispiel:

RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })

Anwendung: Kombination aus Lazy Loading & schneller Navigation.


app-shell

Was:

Statische HTML-Version deiner App für schnelleren First Paint (SEO, Ladezeit).

Anwendungsfall:

Besseres UX bei schlechter Verbindung.

Beispiel:

ng generate app-shell

directive

Was:

Erweiterung von HTML-Elementen (z. B. Hover-Farbe ändern).

Anwendungsfall:

Wiederverwendbares Verhalten.

Beispiel:

@Directive({ selector: '[appHighlight]' })
export class HighlightDirective {
@HostListener('mouseenter') onMouseEnter() { /* Style ändern */ }
}

2. Web Worker – genaueres Beispiel

Ziel: große Fibonacci-Zahl berechnen, ohne UI zu blockieren.

Schritt 1: Worker generieren

ng generate web-worker fibo

fibo.worker.ts

addEventListener('message', ({ data }) => {
const result = fibonacci(data);
postMessage(result);
});

function fibonacci(n: number): number {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}

component.ts

if (typeof Worker !== 'undefined') {
const worker = new Worker(new URL('./fibo.worker', import.meta.url), { type: 'module' });

worker.onmessage = ({ data }) => {
console.log(`Ergebnis: ${data}`);
};

worker.postMessage(40); // Lange Berechnung
}

  constructor(private translate: TranslateService) {
const lang = localStorage.getItem('lang') ?? 'en';
this.switchLanguage(lang)
}
switchLanguage(lang: string) {
this.translate.use(lang);
localStorage.setItem('lang', lang);
}

Installation (empfohlen):

npm install ngx-indexed-db

Setup (app.module.ts):

import { NgxIndexedDBModule, DBConfig } from 'ngx-indexed-db';

const dbConfig: DBConfig = {
name: 'MyDB',
version: 1,
objectStoresMeta: [
{
store: 'notes',
storeConfig: { keyPath: 'id', autoIncrement: true },
storeSchema: [
{ name: 'title', keypath: 'title', options: { unique: false } },
{ name: 'content', keypath: 'content', options: { unique: false } }
]
}
]
};

@NgModule({
imports: [NgxIndexedDBModule.forRoot(dbConfig)],
})
export class AppModule {}

Nutzung im Service:

constructor(private dbService: NgxIndexedDBService) {}

addNote(note: { title: string; content: string }) {
return this.dbService.add('notes', note);
}

getNotes() {
return this.dbService.getAll('notes');
}

local storage data